/**
  ******************************************************************************
  * @file           : XYXKC_ASR.cpp
  * @author         : admin
  * @brief          : None
  * @attention      : None
  * @date           : 2025/2/27
  ******************************************************************************
  */

#include "XYXKC_ASR.h"
static XYXKC_ASR* instance;
TaskHandle_t myTaskHandle;
XYXKC_ASR::XYXKC_ASR():_webSocket(){
    instance = this;
}
String generateUUID() {
    String uuid = "";
    const char hexChars[] = "0123456789abcdef";

    for (int i = 0; i < 32; i++) {
        // 生成0 - 15之间的随机数
        int randomIndex = random(16);
        // 从hexChars数组中选取对应的字符添加到uuid字符串中
        uuid += hexChars[randomIndex];
    }

    return uuid;
}

void XYXKC_ASR::webSocketEvent(WStype_t type, uint8_t * payload, size_t length) {
    switch (type) {
        case WStype_DISCONNECTED:
            instance->_enableIt = false;
            break;
        case WStype_CONNECTED:
            instance->_webSocket.sendTXT(instance->_jsonString);
            break;
        case WStype_TEXT:
            DynamicJsonBuffer jsonBuffer;
            JsonObject& object = jsonBuffer.parseObject(payload);
            if(object["header"]["name"].as<String>() == "TranscriptionStarted"){
                instance-> _enableIt = true;
            }
            else if(object["header"]["name"].as<String>() == "SentenceEnd"){
                instance->_result = object["payload"]["result"].as<String>();
                instance->_isIdentify = true;
            }
            break;
    }

}


void XYXKC_ASR::_i2sInit(){
    i2s_config_t i2s_config = {
            .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
            .sample_rate =  8000,
            .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
            .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
            .communication_format = I2S_COMM_FORMAT_I2S_MSB,
            .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
            .dma_buf_count = 16,
            .dma_buf_len = 128,
            .use_apll = true,
    };
    i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
    i2s_set_adc_mode(ADC_UNIT_1, ADC_INPUT);
    adc1_config_width(ADC_WIDTH_BIT_12);
    adc1_config_channel_atten(ADC_INPUT, ADC_ATTEN_DB_11);
    i2s_adc_enable(I2S_NUM_0);
}
void XYXKC_ASR::asrInit(String token, String appKey) {
    _jsonString = "{\"header\":{\"message_id\":\""+generateUUID()+"\",\"task_id\":\""+generateUUID()+"\",\"namespace\":\"SpeechTranscriber\",\"name\":\"StartTranscription\",\"appkey\":\""+appKey+"\"},\"payload\":{\"format\":\"pcm\",\"sample_rate\":8000,\"enable_intermediate_result\":true,\"enable_punctuation_prediction\":true,\"enable_inverse_text_normalization\":true}}";
    _i2sInit();
    _token = token;
}
bool XYXKC_ASR::isIdentificationSuccessful(){
    bool b = _isIdentify;
    _isIdentify = false;
   return b;
}
String XYXKC_ASR::getAsrResult() {
    return _result;
}


void XYXKC_ASR:: recordSound(void *pvParameters){
    int16_t buffer[I2S_DMA_BUF_LEN] = {0};
    size_t bytes_read;
    while(true){
        instance->_webSocket.loop();
        i2s_read(I2S_NUM_0, buffer, I2S_DMA_BUF_LEN*sizeof(int16_t), &bytes_read, portMAX_DELAY);
        // 发送二进制数据
        instance->_webSocket.sendBIN((const uint8_t*)buffer, bytes_read);
    }
}


void XYXKC_ASR::enableSpeechRecognition() {
    _webSocket.beginSSL("nls-gateway-cn-shanghai.aliyuncs.com",443,"/ws/v1?token="+_token);
    _webSocket.onEvent(webSocketEvent);
    // webSocket.setAuthorization("user", "Password");

    // webSocket.setReconnectInterval(5000);
    if (myTaskHandle == NULL) {
        xTaskCreatePinnedToCore(
                recordSound,          // 任务函数
                "MyTask",        // 任务名称
                8192,           // 任务堆栈大小
                NULL,            // 传递给任务函数的参数
                5,               // 任务优先级
                &myTaskHandle,   // 任务句柄
                0                // 运行在核心0
        );
    }

}

void XYXKC_ASR::stopSpeechRecognition() {
    vTaskDelete(myTaskHandle);
    _webSocket.disconnect();
}
